2 Custom 'Writers'

OK, lets build a Writer that lets you turn YouTube video URLs into the actual embedded videos. Say you have a website which lets users copy and paste the URL of their favourite Youtube video into a text field, but when it is shown to visitors of the profile page, you want to show the embedded video instead of just the URL link.

The first thing to note is the minor difference between the YouTube webpage URL for a video, and the embedabble URL for a video. My current perpetual nerd crush is Scott Hanselman so I've chosen a video starring him...

Video URL:

http://www.youtube.com/watch?v=NuIsBO9HifY

Embed Code:

<iframe width="420" height="315" src="http://www.youtube.com/embed/NuIsBO9HifY" frameborder="0" allowfullscreen></iframe>

The metadata object is simple, just the original URL and a Type. The "businessObject" writer also allows you to set "onCreate", "onUpdate" and "onDelete" properties, which are the names of actions (functions, added to $.meteoric.actions - see below) called when the "Create", "Update" or "Delete" buttons are pressed, when the context.mode has been set to one of those three modes.

// Build the entity
var entity = {
	"type": "businessObject",
	"name": "YouTube",
	"action": "YouTube",
	"onCreate": "onCreate",
	"onUpdate": "onUpdate",
	"onDelete": "onDelete",
	"fields": [{
		"name": "FavouriteYouTubeVid",
		// new "type" - so we need to create a writer
		"type": "youtube",
		"displayName": "Favourite YouTube Video:",
		// We can cheat and re-use the "string" writer for 
		Create/Update scenarios. So this entity must be able to provide the 
		information that the string writer needs to run
		"value": "http://www.youtube.com/watch?v=NuIsBO9HifY",
		"maxLength": 90,
		"minLength": 2,
		"isRequired": true,
		"placeholder": "Favourite YouTube video:"
	}]
};

// Create actions
$.meteoric.actions.onCreate = function (event, entity) {
	alert("Added your favourite YouTube video!");
}
$.meteoric.actions.onUpdate = function (event, entity) {
	alert("Updated your favourite YouTube video!");
}
$.meteoric.actions.onDelete = function (event, entity) {
	if (confirm("Are you sure you want to delete this?")) {
		alert("Deleted!");
	} else {
		alert("Delete ABORTED.");
	}
}

// Create a writer for the 'youtube' type:
$.meteoric.writers.youtube = function (context, entity) {
	var fieldDisplay;

	if (context.mode == "read") {
		// Replace the video URL with the embedded video source
		fieldDisplay = $('<iframe width="420" height="315" src="' + 
						entity.value.split("watch?v=").join("embed/") + '" 
						frameborder="0" allowfullscreen>');;
    
	} else {
		// Delegate all other types of writing to the standard "string" writer
		// The third parameter is the name of the writer to use instead:
		context.build(context, entity, "string");
	}
	context.parent.append(fieldDisplay);
};


$("#meteoricRead").meteoric({ entity: entity });
$("#meteoricCreate").meteoric({ entity: entity, mode: "create" });
$("#meteoricUpdate").meteoric({ entity: entity, mode: "update" });
$("#meteoricDelete").meteoric({ entity: entity, mode: "delete" });

Output: